home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
prog_c
/
cuj0696.zip
/
DWYER.ZIP
/
LIB
/
MARSAG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-26
|
9KB
|
284 lines
/* marsag.c */
/* -------------------------------------------------------------------- *
* This random number generator originally appeared in "Toward a *
* Universal Random Number Generator" by George Marsaglia and Arif *
* Zaman. Florida State University Report: FSU-SCRI-87-50 (1987) *
* *
* It was later modified by F. James and published in "A Review of *
* Pseudo-random Number Generators" *
* *
* THIS IS THE BEST KNOWN RANDOM NUMBER GENERATOR AVAILABLE. *
* (But, a newly discovered technique can yield a period of 10^600. *
* But that is still in the development stage.) *
* *
* It passes ALL of the tests for random number generators and has a *
* period of 2^144, is portable (gives bit-identical results on all *
* machines with at least 24-bit mantissas in the floating point *
* representation). *
* *
* The algorithm is a combination of a Fibonacci sequence (with lags of *
* 97 and 33, an operation "subtraction plus one, modulo one") and an *
* "arithmetic sequence" (using subtraction). *
* ==================================================================== *
* This C language version was written by Jim Butler, and is based on a *
* FORTRAN program posted by David LaSalle of Florida State University. *
* -------------------------------------------------------------------- */
#include <stdlib.h>
#define FULL_SIZE ((unsigned)RAND_MAX + 1U)
/* ------------------- */
/* FUNCTION PROTOTYPES */
/* ------------------- */
# undef F
# if defined(__STDC__) || defined(__PROTO__)
# define F( P ) P
# else
# define F( P ) ()
# endif
/* INDENT OFF */
extern double Dranmar F((void));
extern int Iranmar F((void));
extern void ranmar F((double *, int));
extern void rmarin F((unsigned, unsigned));
# undef F
/* INDENT ON */
# if defined(TEST_MARSAG)
#include <stdio.h>
void
main()
{
double temp[100];
int ij, kl, len, i;
/* random seeds for the test case: */
ij = 1802;
kl = 9373;
#if 0
/* do the initialization */
rmarin(ij, kl);
# endif
/* generate 20,000 random numbers */
len = 100;
for (i = 1; i <= 200; i++)
ranmar(temp, len);
/*
* If the random number generator is working properly, the next six
* random numbers should be:
*
* 6533892.0 14220222.0 7275067.0 6172232.0 8354498.0 10633180.0
*/
len = 6;
ranmar(temp, len);
for (i = 0; i < 6; i++)
printf("%12.1f", 4096.0 * 4096.0 * temp[i]);
printf("\nCompare:\n 6533892.0 14220222.0 7275067.0 "
" 6172232.0 8354498.0 10633180.0\n");
}
# endif
/* ---------------------------------------------------------- */
/* Initialized Table. These numbers have values identical to */
/* those created when function rmarin() is called as follows: */
/* */
/*- int ij, kl; */
/* */
/*- ij = 1802; */
/*- kl = 9373; */
/* */
/* rmarin(ij, kl); */
/* ---------------------------------------------------------- */
/* INDENT OFF */
#define _D_ 16777216.0
static double u[98] =
{
0.0 , 13697435.0 / _D_, 3833429.0 / _D_,
12353926.0 / _D_, 2287754.0 / _D_, 3468638.0 / _D_,
1232959.0 / _D_, 8059805.0 / _D_, 10745739.0 / _D_,
4236676.0 / _D_, 2095136.0 / _D_, 1349346.0 / _D_,
3672867.0 / _D_, 14563641.0 / _D_, 15473517.0 / _D_,
9897259.0 / _D_, 2207061.0 / _D_, 929657.0 / _D_,
8109095.0 / _D_, 5246947.0 / _D_, 1066111.0 / _D_,
8460236.0 / _D_, 13162386.0 / _D_, 501474.0 / _D_,
10402355.0 / _D_, 352505.0 / _D_, 2104170.0 / _D_,
12045925.0 / _D_, 4350943.0 / _D_, 13996856.0 / _D_,
9897761.0 / _D_, 6626452.0 / _D_, 15057436.0 / _D_,
3168599.0 / _D_, 14038489.0 / _D_, 8550848.0 / _D_,
5242835.0 / _D_, 13296102.0 / _D_, 11969002.0 / _D_,
95246.0 / _D_, 5917978.0 / _D_, 8555838.0 / _D_,
13557738.0 / _D_, 1526088.0 / _D_, 11197237.0 / _D_,
15721125.0 / _D_, 14247931.0 / _D_, 897046.0 / _D_,
15537441.0 / _D_, 16645456.0 / _D_, 16279884.0 / _D_,
1289925.0 / _D_, 14032128.0 / _D_, 10641039.0 / _D_,
9961793.0 / _D_, 2737638.0 / _D_, 5073398.0 / _D_,
5231619.0 / _D_, 2007688.0 / _D_, 15753584.0 / _D_,
12368695.0 / _D_, 12926325.0 / _D_, 10522018.0 / _D_,
8692194.0 / _D_, 8531802.0 / _D_, 14755384.0 / _D_,
276334.0 / _D_, 9157821.0 / _D_, 989353.0 / _D_,
6093627.0 / _D_, 15866666.0 / _D_, 9532882.0 / _D_,
3434034.0 / _D_, 710155.0 / _D_, 672726.0 / _D_,
12734991.0 / _D_, 13809842.0 / _D_, 4832132.0 / _D_,
9753458.0 / _D_, 11325486.0 / _D_, 12137466.0 / _D_,
3617374.0 / _D_, 4913050.0 / _D_, 9978642.0 / _D_,
12740205.0 / _D_, 15754026.0 / _D_, 4928136.0 / _D_,
8545553.0 / _D_, 12893795.0 / _D_, 8164497.0 / _D_,
12420478.0 / _D_, 8192378.0 / _D_, 2028808.0 / _D_,
1183983.0 / _D_, 3474722.0 / _D_, 15616920.0 / _D_,
16298670.0 / _D_, 14606645.0 / _D_
};
static double c = 362436.0 / 16777216.0,
cd = 7654321.0 / 16777216.0,
cm = 16777213.0 / 16777216.0;
static int i97 = 97, j97 = 33;
/* INDENT ON */
/* -------------------------------------------------------------------- *
* This is the initialization routine for the random number generator *
* RANMAR(). NOTE: The seed variables can have values between: *
* *
* 0 <= IJ <= 31328 *
* 0 <= KL <= 30081 *
* *
* The random number sequences created by these two seeds are long *
* enough to complete an entire calculation with. For example, if *
* several different groups are working on different parts of the *
* same calculation, each group could be assigned its own IJ seed. *
* This would leave each group with 30000 choices for the second *
* seed. That is to say, this random number generator can create *
* 900 million different subsequences, each subsequence having a *
* length of approximately 10^30. *
* *
* Use IJ = 1802 & KL = 9373 to test the random number generator. *
* First, subroutine RANMAR should be used to generate 20000 random *
* numbers. Then display the next six random numbers generated each *
* multiplied by 4096*4096. If the random number generator is working *
* properly, the random numbers should be: *
* *
* 6533892.0 14220222.0 7275067.0 6172232.0 8354498.0 10633180.0 *
* -------------------------------------------------------------------- */
# if defined(__STDC__) || defined(__PROTO__)
void
rmarin(unsigned IJ, unsigned KL)
# else
void
rmarin(IJ, KL)
unsigned IJ;
unsigned KL;
# endif
{
int i, ij, j, k, kl, l, ii, jj, m;
double s, t;
ij = IJ % 31329;
kl = KL % 30082;
i = (ij / 177) % 177 + 2;
j = ij % 177 + 2;
k = (kl / 169) % 178 + 1;
l = kl % 169;
for (ii = 1; ii <= 97; ii++)
{
s = 0.0;
t = 0.5;
for (jj = 1; jj <= 24; jj++)
{
m = (((i * j) % 179) * k) % 179;
i = j;
j = k;
k = m;
l = (53 * l + 1) % 169;
if ((l * m) % 64 >= 32)
s += t;
t *= 0.5;
}
u[ii] = s;
}
/* INDENT OFF */
c = 362436.0 / 16777216.0;
cd = 7654321.0 / 16777216.0;
cm = 16777213.0 / 16777216.0;
/* INDENT ON */
i97 = 97;
j97 = 33;
}
/* ==================================================================== */
/* Dranmar - returns pseudo random double in [0, 1) */
/* ==================================================================== */
double
Dranmar()
{
double uni;
uni = u[i97] - u[j97];
if (uni < 0.0)
{
uni += 1.0;
}
u[i97] = uni;
i97--;
if (i97 == 0)
{
i97 = 97;
}
j97--;
if (j97 == 0)
{
j97 = 97;
}
c -= cd;
if (c < 0.0)
{
c += cm;
}
uni -= c;
if (uni < 0.0)
{
uni += 1.0;
}
return uni;
}
/* ==================================================================== */
/* Iranmar - returns pseudo random integer in [0, RAND_MAX] */
/* ==================================================================== */
int
Iranmar()
{
return((int) ((double)FULL_SIZE * Dranmar()) & RAND_MAX);
}
/* -------------------------------------------- */
/* ranmar - places len random numbers in rvec[] */
/* -------------------------------------------- */
# if defined(__STDC__) || defined(__PROTO__)
void
ranmar(double *rvec, int len)
# else
void
ranmar(rvec, len)
double *rvec;
int len;
# endif
/* -------------------------------------------------------------------- *
* This is the random number generator proposed by George Marsaglia *
* in Florida State University Report: FSU-SCRI-87-50. *
* It was slightly modified by F. James to produce an array of *
* pseudorandom numbers. *
* -------------------------------------------------------------------- */
{
int ivec;
for (ivec = 0; ivec < len; ++ivec)
{
rvec[ivec] = Dranmar();
}
}